package utils

import "sync"

// ListItem 双向链表
type ListItem struct {
	Data interface{}
	Prev *ListItem
	Next *ListItem
}

func NewListItem(data interface{}) *ListItem {
	return &ListItem{
		Data: data,
	}
}

// First 获取第一个元素
func (l *ListItem) First() *ListItem {
	prev := l.Prev
	if prev == nil {
		return l
	}
	for {
		if nil == prev.Prev {
			return prev
		}
		prev = prev.Prev
	}
}

// End 获取最后一个元素
func (l *ListItem) End() *ListItem {
	next := l.Next
	if nil == next {
		return l
	}
	for {
		if nil == next.Next {
			return next
		}
		next = next.Next
	}
}

// Count 获取元素数量
func (l *ListItem) Count() int {
	first := l.First()

	count := 1

	for {
		next := first.Next
		if next == nil {
			return count
		}
		count++
		first = first.Next
	}
}

// Index 按序号取元素
func (l *ListItem) Index(i int) *ListItem {
	item := l.First()
	count := 0
	for {
		if count == i {
			return item
		}

		item = item.Next
		if nil == item {
			return nil
		}
		count++
	}
}

func (l *ListItem) Remove(i int) *ListItem {
	itm := l.Index(i)
	if nil != itm {
		prev := itm.Prev
		next := itm.Next
		if next != nil {
			next.Prev = prev
		}
		if prev != nil {
			prev.Next = next
		}
		if prev == nil && next == nil {
			return nil
		}
		if prev != nil {
			return prev.First()
		} else if next != nil {
			return next.First()
		}
	}
	return l.First()
}

// Pop 弹出第一个元素
func (l *ListItem) Pop() (*ListItem, *ListItem) {
	pop := l.First()
	next := pop.Next
	pop.Next = nil
	if nil != next {
		next.Prev = nil
	}
	return pop, next
}

// Push 头部插入元素
func (l *ListItem) Push(item *ListItem) (first *ListItem) {
	first = l.First()
	first.Prev = item
	item.Next = first
	item.Prev = nil
	return item
}

func (l *ListItem) Append(item *ListItem) {
	end := l.End()
	end.Next = item
	item.Prev = end
}

// Walk 遍历执行所有元素
func (l *ListItem) Walk(fun func(interface{}) bool) {
	first := l.First()
	for {
		b := fun(first.Data)
		if false == b {
			return
		}
		first = first.Next
		if first == nil {
			return
		}
	}
}

// Find 查找元素
func (l *ListItem) Find(fun func(interface{}) bool) (*ListItem, int) {

	first := l.First()
	idx := 0
	for {
		b := fun(first.Data)
		if true == b {
			return first, idx
		}
		first = first.Next
		if first == nil {
			return nil, -1
		}
		idx++
	}
}

func (l *ListItem) FindAndRemove(fun func(interface{}) bool) *ListItem {
	_, idx := l.Find(fun)
	if idx != -1 {
		return l.Remove(idx)
	}
	return l.First()
}

// StringArray 字符串数据列表
type StringArray struct {
	arr []string
	mu  sync.RWMutex
}

func (s *StringArray) Find(data string) int {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for idx, str := range s.arr {
		if str == data {
			return idx
		}
	}
	return -1
}

func (s *StringArray) Add(data string) {
	s.mu.Lock()
	defer s.mu.Unlock()
	for _, str := range s.arr {
		if str == data {
			return
		}
	}
	s.arr = append(s.arr, data)
}

func (s *StringArray) Remove(data string) {
	s.mu.Lock()
	defer s.mu.Unlock()
	for idx, str := range s.arr {
		if str == data {
			s.arr = append(s.arr[:idx], s.arr[idx+1:]...)
			return
		}
	}
}
